#! user/bin/python
# -*- coding: utf-8 -*-

"""
Created on 2021/8/20 10:41

@File: test-socket_stream_redirect.py
@Author: LT
@Description: 应该把socket看作端点，socket是服务器与连接上它的客户端的共用的一线量端
              使用了makefile以后，可以将print比作往socketsend；将input比作从socket读
                        ↙↖      -------------------        ↗↘
              服务器端      socket                    socket     客户端
                        ↖↙      -------------------        ↘↗
"""
import sys, os, multiprocessing
from 使套接字看起来像文件和数据流_流重定向实用程序_socket_stream_redirect import *


##################################################################
# 被重定向了的 客户端 输出
##################################################################
def server1():
    mypid = os.getpid()
    conn = initListenerSocket()                                             # 会阻塞，直到客户端连接上来
    file = conn.makefile("r")
    for i in range(3):
        data = file.readline().strip()
        print("server %s got [%s]" % (mypid, data))


def client1():
    mypid = os.getpid()
    redirectOut()
    for i in range(3):
        print("client %s: %s" % (mypid, i))                                 # 打印到套接字
        sys.stdout.flush()                                                  # 否则刷到缓冲区，直到退出？


##################################################################
# 被重定向了的 客户端 输入
##################################################################
def server2():
    mypid = os.getpid()
    conn = initListenerSocket()                                             # 会阻塞，直到客户端连接上来
    for i in range(3):
        conn.send(("server %s: %s\n" % (mypid, i)).encode())


def client2():
    mypid = os.getpid()
    redirectIn()                                                            # 这一步是连接上了客户端
    for i in range(3):
        data = input()                                                      # 然后是重定向了服务器的send作为客户端的input
        print("client %s: %s" % (mypid, data))                              # 正常打印到终端


##################################################################
# 重定向客户端的  输入+输出，客户端是个套接字客户端
##################################################################
def server3():
    mypid = os.getpid()
    conn = initListenerSocket()                                             # 等待客户端接入
    file = conn.makefile('r')                                               # 接收print(), 回复input()
    for i in range(3):                                                      # readline会阻塞住直到data
        data = file.readline().rstrip()                                     # 客户端的print会在这读取为data
        conn.send(('server %s got [%s]\n' % (mypid, data)).encode())


def client3():
    mypid = os.getpid()
    redirectBothAsClient()
    for i in range(3):
        print('client %s: %s' % (mypid, i))                                 # print会被重定向到socket
        data = input()                                                      # 从socket来的input会刷进流中，而不是重定向
        sys.stderr.write('client %s got [%s]\n' % (mypid, data))


###############################################################################
# 重定向客户端的  输入+输出，原客户端现在是个套接字服务器，原服务器现在是个客户端
###############################################################################
def server4():
    """此时我转变成了一个客户端，因为我用了connect方法"""
    mypid = os.getpid()
    sock = socket(AF_INET, SOCK_STREAM)
    sock.connect((host, port))
    file = sock.makefile('r')                                               # 它只重定向了socket的recv方法
    for i in range(3):
        sock.send(('server %s: %s\n' % (mypid, i)).encode())                # 发送到客户端的input()中去
        data = file.readline().rstrip()                                     # 从客户端的print()中接收数据
        print('server %s got [%s]' % (mypid, data))                         # 打印到服务器终端


def client4():
    mypid = os.getpid()
    redirectBothAsServer()                                                  # I'm actually the socket server in this mode
                                                                            # 在这个模式下，我实际上是个套接字服务器，虽然我的名字叫client
    for i in range(3):
        data = input()                                                      # input是从socket套接字流中冲刷过来的！
        print('client %s got [%s]' % (mypid, data))                         # 打印给socket套接字
        sys.stdout.flush()                                                  # else last buffered till exit!


###############################################################################
# 重定向 客户端的 input和output， 客户端就是套接字的客户端，服务器端先处理xfers？
# redirect client input + output, client is socket client, server xfers first
###############################################################################

def server5():
    mypid = os.getpid()                                                     # test 4, but server accepts
    conn = initListenerSocket()                                             # 等待客户端的连接
    file = conn.makefile('r')                                               # 发送 input(), 接收 print()
    for i in range(3):
        conn.send(('server %s: %s\n' % (mypid, i)).encode())
        data = file.readline().rstrip()
        print('server %s got [%s]' % (mypid, data))


def client5():
    mypid = os.getpid()
    s = redirectBothAsClient()                                              # 在这个模式下，我实际上是个套接字客户端
    for i in range(3):
        data = input()                                                      # input from socket: flushes!
        print('client %s got [%s]' % (mypid, data))                         # 打印到 socket套接字
        sys.stdout.flush()                                                  # 否则持续输出到缓冲区直到退出!


###############################################################################
# 根据命令行给出的数字来进行测试
###############################################################################

if __name__ == '__main__':
    # 像这样运行：python .\test-socket_stream_redirect.py 2
    server = eval('server' + sys.argv[1])
    client = eval('client' + sys.argv[1])                                   # client in this process
    multiprocessing.Process(target=server).start()                          # server in new process
    client()                                                                # 重设客户端的流方式
    # import time; time.sleep(5)                                            # 测试退出对缓冲区的影响
